﻿package net.libra.utils
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.TimerEvent;
	import flash.net.LocalConnection;
	import flash.system.System;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	import flash.utils.getTimer;

	/**
	 * @author DanielLu
	 */
	public class GCManager 
	{
		private static var dictionary : Dictionary = new Dictionary( true );
		private static var delayTime : int = - 1;
		private static var listener : Function;
		//计时器
		private static var timer : Timer = new Timer( 1000 );
		{
		GCManager.timer.addEventListener( TimerEvent.TIMER , __onTrace );
		GCManager.timer.addEventListener( TimerEvent.TIMER , __onDoGC );
		}

		private static function __onTrace (e : TimerEvent) : void
		{
			//显示已被监视的对象
			var str : String = "";
			str += "===================================== GCWatching Begin =====================================\n";
			for(var value:* in GCManager.dictionary)
			{
				str += "value：" + value + "\n";
				//清除引用
				value = null;
			}
			str += "运行 " + int( getTimer( ) / 1000 / 60 ) + " 分钟，当前使用的系统内存: ";
			str += Math.round( System.totalMemory / 1000 ) + " k";
			str += "\n";
			str += "===================================== GCWatching  End  =====================================\n";
			trace( str );
		}

		private static function __onDoGC (e : TimerEvent) : void
		{
			if(GCManager.delayTime > 0 && GCManager.timer.currentCount > GCManager.delayTime )
			{
				if(GCManager.listener != null)GCManager.listener( );
				GCManager.listener = null;
				GCManager.doGC( );
			}
		}

		/**
		 * 添加对象至内存监视。添加的对象将会被打印，用于方便的监视对象在内存中的存在情况。
		 * @param o		要监视的对象。
		 */
		public static function addMonitor (o : Object) : void
		{
			GCManager.dictionary[o] = null;
		}

		/**
		 * 启动监测器，监测系统使用的内存。
		 * @param delayTime		当显示多少次信息之后，自动做一次垃圾回收。如果小于等于0，则表示不自动执行垃圾回收。
		 * @param listener		在执行垃圾回收之前的回调函数。此方法用于清除一些引用，用于测试。
		 * @param delay			显示信息的间隔
		 */
		public static function startMonitor (delayTime : int = - 1,listener : Function = null,delay : int = 1000) : void
		{
			GCManager.delayTime = delayTime;
			GCManager.listener = (listener == null) ? null : listener;
			GCManager.timer.delay = delay;
			if(! GCManager.timer.running)
			{
				GCManager.timer.start( );
			}
		}

		/**
		 * 停止监测系统使用的内存。
		 */
		public static function stopMonitor () : void
		{
			GCManager.timer.stop( );
		}

		/**
		 * 强制垃圾回收。
		 */
		public static function doGC () : void
		{
			try
			{
				new LocalConnection( ).connect( "DanielLab" );
				new LocalConnection( ).connect( "DanielLab" );
			}
			catch(e : Error)
			{
				trace( "垃圾回收已运行" );
			}
		}

		/**
		 * 添加显示对象以及其所有的子显示对象至内存监视。方法会自动递归至所有的显示子级对象。
		 * @param dc		显示对象容器。
		 */
		public static function addMoniteContainer (dc : DisplayObjectContainer) : void
		{
			for(var i : int; i < dc.numChildren ; i ++)
			{
				var child : DisplayObject = dc.getChildAt( i );
				if(child is DisplayObjectContainer)
				{
					GCManager.addMonitor( child as DisplayObjectContainer );
				}
				GCManager.addMonitor( child );
			}
		}
	}
}
